Crate aws_sig_auth

source ·
Expand description

AWS Signature Authentication Package

This crate may be used to generate presigned URLs for unmodeled behavior such as rds-iam-token or to sign requests to APIGateway-based services with IAM authorization.

Examples

Generate RDS IAM Token

use aws_credential_types::Credentials;
use aws_smithy_http::body::SdkBody;
use aws_types::SigningService;
use aws_types::region::{Region, SigningRegion};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use aws_sig_auth::signer::{self, SigningError, OperationSigningConfig, HttpSignatureType, RequestConfig};

fn generate_rds_iam_token(
    db_hostname: &str,
    region: Region,
    port: u16,
    db_username: &str,
    credentials: &Credentials,
    timestamp: SystemTime,
) -> Result<String, SigningError> {
    let signer = signer::SigV4Signer::new();
    let mut operation_config = OperationSigningConfig::default_config();
    operation_config.signature_type = HttpSignatureType::HttpRequestQueryParams;
    operation_config.expires_in = Some(Duration::from_secs(15 * 60));
    let request_config = RequestConfig {
        request_ts: timestamp,
        region: &SigningRegion::from(region),
        service: &SigningService::from_static("rds-db"),
        payload_override: None,
    };
    let mut request = http::Request::builder()
        .uri(format!(
            "http://{db_hostname}:{port}/?Action=connect&DBUser={db_user}",
            db_hostname = db_hostname,
            port = port,
            db_user = db_username
        ))
        .body(SdkBody::empty())
        .expect("valid request");
    let _signature = signer.sign(
        &operation_config,
        &request_config,
        &credentials,
        &mut request,
    )?;
    let mut uri = request.uri().to_string();
    assert!(uri.starts_with("http://"));
    let uri = uri.split_off("http://".len());
    Ok(uri)
}

// You will need to get `credentials` from a credentials provider ahead of time
let token = generate_rds_iam_token(
    "prod-instance.us-east-1.rds.amazonaws.com",
    Region::from_static("us-east-1"),
    3306,
    "dbuser",
    &credentials,
    // this value is hard coded to create deterministic signature for tests. Generally,
    // `SystemTime::now()` should be used
    UNIX_EPOCH + Duration::from_secs(1635257380)
).expect("failed to generate token");

Sign a request for APIGateway execute-api

use aws_credential_types::provider::ProvideCredentials;
use aws_sig_auth::signer::{OperationSigningConfig, RequestConfig, SigV4Signer};
use aws_smithy_http::body::SdkBody;
use aws_types::region::{Region, SigningRegion};
use aws_types::SigningService;
use std::error::Error;
use std::time::SystemTime;
async fn sign_request(
    mut request: &mut http::Request<SdkBody>,
    region: Region,
    credentials_provider: &impl ProvideCredentials,
) -> Result<(), Box<dyn Error + Send + Sync>> {
    let now = SystemTime::now();
    let signer = SigV4Signer::new();
    let request_config = RequestConfig {
        request_ts: now,
        region: &SigningRegion::from(region),
        service: &SigningService::from_static("execute-api"),
        payload_override: None,
    };
    signer.sign(
        &OperationSigningConfig::default_config(),
        &request_config,
        &credentials_provider.provide_credentials().await?,
        &mut request,
    )?;
    Ok((()))
}

Modules